//数据过滤相关接口
type PickBy<Base, TargetType> = {
    [Key in keyof Base]: Base[Key] extends TargetType ? Key : never;
}[keyof Base];
/**
* 玩家数据中心，玩家数据的获取，设置，改变及其他相关逻辑
*/
let GData = new class {

    /**玩家的所有数据  
     * 可自由添加和扩展其他属性  
     */
    private _allData = {
        /**玩家的金钱 */
        Money: 520,
        /**玩家唯一标示uid */
        Uid: "123456",
        /**玩家昵称 */
        Nick: "Tom",
        /**当前等级 */
        Lv: 10,
        /**钻石数量 */
        Diamod: 100,
    };

    /**获取玩家的数据       
     * @param key 要获取的属性
     * @example
     * GData.get("Money");
     */
    get<T extends keyof typeof GData._allData>(key: T): typeof GData._allData[T] {
        return this._allData[key];
    }

    /**设置玩家的数据
     * @param key 要设置的属性
     * @param value 要设置的值
     * @example
     * GData.set("Money", 100);
     */
    set<T extends keyof typeof GData._allData>(key: T, value: typeof GData._allData[T]) {
        this._allData[key] = value;
        //可以添加其他逻辑，如：发射事件出去，改变ui表现，实现数据和表现的绑定
    }

    /**改变玩家数值类型的数据，返回当前的数值  
     * @param key 要改变的属性
     * @param changes 变化值  >0表示增加  <0表示减小
     * @param canNegative 改变后的值是否能为负数，可选，默认不能为负数
     * @example
     * //通用：
     * GData.change("Money", -100); // 改变后的值如果为负数则会报错，并且改变不生效
     * //特殊：
     * GData.change("Money", -100, true); // 改变后的值可以为负数了，改变直接生效
     */

    change(key: PickBy<typeof GData._allData, number>, changes: number, canNegative = false) {
        let oldData = this.get(key);
        //数据类型检查
        if (typeof oldData == "number") {
            let newData = oldData + changes;
            //数据范围检查
            if (canNegative || newData >= 0) {
                GData.set(key, <any>newData);
            } else {
                console.error("数值变化后为不合法的负数，此次改变不生效!");
            }
        } else {
            console.error("要改变值不是数字类型!");
        }
        return this.get(key);
    }

}();
window["GData"] = GData;